#pragma once

#define MAX_MATERIAL_STACK_SIZE 4
#define CONST_BUFFER_SIZE		8388608 //8 * 1024*1024 bytes = 8 MB

namespace EMaterialDesc
{
	enum Flag
	{
		UseBumpmapping				= 1 << 0,
//		UseFog						= 1 << 1,
		UseInstancing				= 1 << 2,

		OutNormal					= 1 << 3,
		OutMaterial					= 1 << 4,

		ColorAsTexture0				= 1 << 5,
		ColorAsColor0				= 1 << 6,
		ColorAsConstant				= 1 << 7,
		EnableInstancing			= 1 << 8
	};
}

struct MaterialDesc
{
	// global
	RBlendState*		m_blendstate;
	RDepthstencilState* m_depthstencilstate;
	RRasterizerState*	m_rasterizerstate;

	//clr
	RTexture*			m_texture0;
	RSamplerState*		m_texture0Sampler;
	glm::vec4			m_color;

	// bumpmapping
	RTexture*			m_Bumpmapping_normal0;
	RSamplerState*		m_Bumpmapping_normal0Sampler;
	float				m_Bumpmapping_TextureMultiplier;
	float				m_Bumpmapping_Strength;

	//
	uint				m_flags;

	MaterialDesc() 
		: m_blendstate(NULL),
		m_depthstencilstate(NULL),
		m_rasterizerstate(NULL),
		m_texture0(NULL),
		m_texture0Sampler(NULL),
		m_color(1.0f, 0.0f, 1.0f, 1.0f),
		m_Bumpmapping_normal0(NULL),
		m_Bumpmapping_normal0Sampler(NULL),
		m_Bumpmapping_TextureMultiplier(1.0f),
		m_Bumpmapping_Strength(0.3f),
		m_flags(0)
	{}
};

class MaterialMgr
{
public:
	MaterialMgr();
	~MaterialMgr();

	void		InitMaterialMgr();

	void		Push();
	void		Pop();

	void		Bind(const RMaterial* material);

	void		SetSampler(const std::string& name, RTexture* texture, RSamplerState* sampler);

	const RMaterial*	GetMaterialFromMaster(const MaterialDesc& desc);

private:
	void		Bind(const RBlendState* state);
	void		Bind(const RRasterizerState* state);
	void		Bind(const RDepthstencilState* state);

	const RMaterial*				m_material;
	const RRasterizerState*			m_activeRasterizerState;
	const RBlendState*				m_activeBlendState;
	const RDepthstencilState*		m_activeDepthstencilState;

	std::stack<const RMaterial*>	m_stack;

	RBuffer*				m_constantBuffer;
	uint					m_constantOffset;
};

